import {assign} from './global.js';

class Dragsort {

    node = null;
    el = null;
    moveClass = "drager-move";
    config  = null;
    callback = null;
    callbackTimer =  0;
    constructor(el,config) {

        let _config  = {
            moving:'drager-move',
            callback:()=>{},
            filter:()=>{ return true; },
            start:()=>{ return true },
            end:()=>{ return true },
            move:()=>{}
        }
        
        assign(_config,config);

        this.config = _config ;
        
        this.el = el;
        
        this.init();
    }

    findNode(node){
        while(node.parentNode != this.el){
            node = node.parentNode;
        }

        return node;
    }

    init() {
        this.el.addEventListener('dragstart',(event)=>{

            this.node = this.findNode(event.target);
            
            if (!this.config.start(this.node)) return;
            
            setTimeout(()=>{
                this.node.classList.add(this.config.moving);
            },0);

            event.dataTransfer.effectAllowed = 'move';
            
        });

        this.el.addEventListener('dragover',(event)=>{    
            event.preventDefault();
        });


        this.el.addEventListener('dragenter',(event)=>{
             
            event.preventDefault();
            if (event.target === this.el || event.target === this.node){
               return ;
            }

            const children = Array.from(this.el.children);
            const sourceIndex = children.indexOf(this.node);
           
            let target =  this.findNode(event.target) ;
            
            if (!this.config.filter(this.node,target,event.dataTransfer)) return ;

            let  targetIndex = children.indexOf(target);
            if (targetIndex<0) return ;
            
            if (sourceIndex < targetIndex){
                this.el.insertBefore(this.node,target.nextElementSibling);
            }else{
                this.el.insertBefore(this.node,target);
            }

            this.config.move(target);
        })


        this.el.addEventListener('dragend',(event)=>{
            this.node.classList.remove(this.config.moving);
            
            clearTimeout(this.callbackTimer);
            this.callbackTimer = setTimeout(()=>{
                let value  = [];
                for (let i = 0; i < this.el.children.length; i++) {
                    if (this.config.end(this.node,this.el.children[i])){
                        value.push(this.el.children[i].dataset.drag);
                    }
                }
                
                if (this.config.callback) this.config.callback(value);
            },0);
            
        });


    }
}

export default Dragsort;